import {Component, Input, OnInit, Output, EventEmitter, AfterViewInit} from '@angular/core';
import {FrontPageService} from '../../front-page.service';
import {HttpService} from '@kylin/http';
import {Image} from 'ol/layer';
import {ImageWMS} from 'ol/source';
import {Map} from 'ol';
import * as _ from 'lodash';
import {ConfigService} from '@kylin/config';
import {LayersPanelService} from '../layers-panel.service';
import {DndDropEvent, DropEffect} from 'ngx-drag-drop';

@Component({
    selector: 'kylin-layers',
    templateUrl: './layers.component.html',
    styleUrls: ['./layers.component.less']
})
export class LayersComponent implements OnInit, AfterViewInit {

    @Input() map: Map;
    @Output() selectLayerChange = new EventEmitter();
    private layersCollection = {};
    checked = true;
    visible = true;
    layersData = null;

    constructor(public frontPageService: FrontPageService,
                private http: HttpService,
                private configService: ConfigService,
                public layersPanelService: LayersPanelService) {
    }

    ngOnInit() {
        this.frontPageService.layersObservable.subscribe((data: any) => {
            this.clearData();
            this.createLayersData(data);
            const keys = Object.keys(data.layersMap);
            keys.forEach((key, index) => {
                let finish = false;
                if (index === keys.length - 1) {
                    finish = true;
                }
                this.fetchLayerData(key, finish, data.layersId);
                this.frontPageService.$locationLonLat(key);
            });
        });
    }

    ngAfterViewInit(): void {

    }

    changeListOrder(parentKey, childKey, type) {
        const target = [...this.layersData];
        let targetIndex = null;
        let targetArr = null;
        target.map(i => {
            if (i.key === parentKey) {
                i.child.map((child, index) => {
                    if (child.key === childKey) {
                        targetIndex = index;
                        targetArr = i.child;
                    }
                })
            }
        });
        const cloneTargetArr = [...targetArr];
        if (type === 'up') {
            targetArr[targetIndex - 1] = cloneTargetArr[targetIndex];
            targetArr[targetIndex] = cloneTargetArr[targetIndex - 1];
        } else {
            targetArr[targetIndex + 1] = cloneTargetArr[targetIndex];
            targetArr[targetIndex] = cloneTargetArr[targetIndex + 1];
        }
        this.layersData = target;
        this.changeLayerOrder(targetArr);
    }

    changeLayerOrder(targetArr) {
        const cloneTargetArr = [...targetArr].reverse();
        const indexObj = {};
        cloneTargetArr.map((value, index) => {
            indexObj[value.key] = index;
        });
        _.forIn(this.layersCollection, (value: any, key: string) => {
            value.setZIndex(indexObj[key]);
        })
    }

    clearData() {
        _.forIn(this.layersCollection, (value, key) => {
            this.map.removeLayer(this.layersCollection[key]);
            delete this.layersCollection[key];
        });
        this.layersCollection = {};
        this.layersData = null;
        this.selectLayerChange.emit(null);
    }

    createLayersData(data?: any) {
        const parent: any = {title: data.layersName, key: data.layersId, check: true, visible: true};
        const child = [];
        _.forIn(data.layersMap, (value, key) => {
            child.push({
                ...value,
                title: value.layerName,
                select: false,
                check: true,
                key: key,
                downloadUrl: this.configService.imgHostname + value.loadUrl,
                icon: this.configService.geoServerHostname + '/geoserver/wms?REQUEST=GetLegendGraphic&VERSION=1.0.0&FORMAT=image/png&WIDTH=20&HEIGHT=20&STRICT=false&style=' + value.styleName + `&time=${new Date().getTime()}`
            })
        });
        if (child.length > 0) {
            parent.child = child;
        }
        this.layersData = [parent];
        if (data && data.options && data.options.layerId && data.options.layerName) {
            this.layerTitleClick(data.options.layerId, data.options.layerName);
        }
    }

    layerIconClick(key, title) {
        return;
        const data = {
            layerId: key,
            layerName: title,
            layer: this.layersCollection[key]
        };
        this.selectLayerChangeEmit(data);
        this.layersPanelService.$changeTitleObservable('地图符号化');
    }

    layerCheckChange($event, type: 'parent' | 'child', key: string) {
        switch (type) {
            case 'parent':
                this.layersData.map(i => {
                    if (i.key === key) {
                        i.child.map((value, index) => {
                            value.check = $event;
                            this.changeLayerVisible(value.key, $event);
                        });
                    }
                });
                break;
            case 'child':
                let parentKey = null;
                let childIndex = null;
                this.layersData.map(i => {
                    i.child.map((value, index) => {
                        if (value.key === key) {
                            parentKey = i.key;
                            childIndex = index;
                            this.changeLayerVisible(key, $event)
                        }
                    });
                });
                this.parentCheckboxCheck(parentKey, $event, key, childIndex);
                break;
        }
    }

    private parentCheckboxCheck(parentKey: string, currentState, currentKey, childIndex) {
        this.layersData.map(i => {
            if (i.key === parentKey) {
                const child = i.child;
                let target = null;
                const result = child.some((value, index) => {
                    if (childIndex === 0) {
                        if (child.length === 1) {
                            target = child[0];
                        } else {
                            target = child[1];
                        }
                    } else {
                        target = child[0]
                    }
                    if (value.key === currentKey) {
                        return currentState === target.check;
                    } else {
                        return value.check === target.check;
                    }
                });
                if (result) {
                    i.check = target.check;
                }
            }
        });
    }

    changeLayerVisible(layerId: string, layerState: string) {
        this.layersCollection[layerId].setVisible(layerState);
    }

    fetchLayerData(layerId: string, finish = false, layersId?: string) {
        this.http.get(`http://192.168.1.100:8091/layer/${layerId}`)
            .then(res => {
                if (res.resp_code === '10000') {
                    res.data.map(e => {
                        if (_.indexOf([1, 2, 3], e.layerType) !== -1) { // 1,2,3是geoJson数据. 4,5,6是geo图层数据
                            // this.addLayerByGeoJson({layerJson: e.layerJson, key: e.layerId}, layersId);
                        } else {
                            this.addLayerByWms({url: e.geoserverUrl, key: e.layerId, finish, layersId: layersId});
                        }
                    })
                }
            })
            .catch(err => {

            })
    }

    private addLayerByWms(options) {
        const data = this.urlResolver(options.url);
        this.layersCollection[options.key] = new Image({
            source: new ImageWMS({
                ratio: 1,
                url: data.url,
                params: {
                    format: 'image/png',
                    version: data.version,
                    style: '',
                    layers: data.layers,
                    time: new Date().getTime()
                }
            }),
            opacity: 0.7
        });
        this.map.addLayer(this.layersCollection[options.key]);
        setTimeout(() => {
            if (options.finish) {
                let targetArr = null;
                this.layersData.map(i => {
                    if (i.key === options.layersId) {
                        targetArr = i.child;
                    }
                });
                this.changeLayerOrder(targetArr);
            }
        })
    }

    private urlResolver(url: string) {
        return {
            url: this.getQueryVariable('url', url),
            layers: this.getQueryVariable('layers', url),
            version: this.getQueryVariable('version', url)
        }
    }

    private getQueryVariable(variable: string, url: string) {
        const vars = url.split('&');
        if (variable === 'url') {
            return vars[0].split('?')[0];
        }
        for (let i = 0; i < vars.length; i++) {
            const pair = vars[i].split('=');
            if (pair[0] === variable) {
                return pair[1];
            }
        }
        return '';
    }

    layerTitleClick(key, title) {
        this.layersData.map(i => {
            i.child.map(child => {
                if (child.key === key) {
                    child.select = !child.select;
                    if (child.select) {
                        const data = {
                            ...child,
                            layerId: key,
                            layerName: title,
                            layer: this.layersCollection[key]
                        };
                        this.selectLayerChangeEmit(data);
                    } else {
                        this.selectLayerChangeEmit(null);
                    }
                } else {
                    child.select = false;
                }
            })
        })
    }

    selectLayerChangeEmit(value) {
        this.selectLayerChange.emit(value);
        this.layersPanelService.$changeSelectLayerObservable(value);
    }

    onDrop(event: DndDropEvent, list?: any[]) {
        if (list && (event.dropEffect === 'copy' || event.dropEffect === 'move')) {
            let index = event.index;
            if (typeof index === 'undefined') {
                index = list.length;
            }
            list.splice(index, 0, event.data);
        }
    }

    onDragStart(event: DragEvent) {

    }

    onDragged(item: any, list: any[], effect: DropEffect) {
        console.log(effect);
        if (effect === 'move') {
            const index = list.indexOf(item);
            list.splice(index, 1);
        }
    }

    onDragEnd(event: DragEvent, list: any[]) {
        this.changeLayerOrder(list);
    }

}
